
//
//	cove.geom.Rectangle - 2011 May 10th
//
//	Creates a new Rectangle object with the top-left corner specified by the x and y parameters and
//	with the specified width and height parameters 
//
//-------------------------------------------------------------------------------------------------

var Rectangle = cove.geom.Rectangle = Class.extend({
	
	init: function(x, y, width, height) {
		this.x = isNaN(x) ? 0 : x;
		this.y = isNaN(y) ? 0 : y;
		this.width = isNaN(width) ? 0 : width;
		this.height = isNaN(height) ? 0 : height;
	},


//	Public properties
//-------------------------------------------------------------------------------------------------
	
	// The sum of the y and height properties.
	get bottom() { return this.y + this.height; },
	set bottom(b) {
		if(!isNaN(b))
			this.height = b - this.y;
	},
	
	// The location of the Rectangle object's bottom-right corner, determined by the values of the
	// right and bottom properties.
	get bottomRight() { return new Point(this.right, this.bottom); },
	set bottomRight(p) {
		if(p instanceof Point) {
			this.right = p.x;
			this.bottom = p.y;
		}
	},
	
	// The x coordinate of the top-left corner of the rectangle.
	get left() { return this.x; },
	set left(b) {
		if(!isNaN(b)) {
			this.width += this.x - b;
			this.x = b;
		}
	},
	
	// The sum of the x and width properties.
	get right() { return this.x + this.width; },
	set right(b) {
		if(!isNaN(b))
			this.width = b - this.x;
	},
	
	// The size of the Rectangle object, expressed as a Point object with the values of the width
	// and height properties.
	get size() { return new Point(this.width, this.height); },
	set size(p) {
		if(p instanceof Point) {
			this.width = p.x;
			this.height = p.y;
		}
	},
	
	// The y coordinate of the top-left corner of the rectangle.
	get top() { return this.y; },
	set top(b) {
		if(!isNaN(b)) {
			this.height += this.y - b;
			this.y = b;
		}
	},
	
	// The location of the Rectangle object's top-left corner, determined by the x and y coordinates
	// of the point.
	get topLeft() { return new Point(this.x, this.y); },
	set topLeft(p) {
		if(p instanceof Point) {
			this.left = p.x;
			this.top = p.y;
		}
	},


//	Public methods
//-------------------------------------------------------------------------------------------------
	
	// Creates a copy of this Rectangle object.
	clone: function() {
		return new Rectangle(this.x, this.y, this.width, this.height);
	},
	
	// Determines whether the specified point is contained within the rectangular region.
	contains: function(x, y) {
		return (
			x >= this.x &&
			x < this.x + this.width &&
			y >= this.y &&
			y < this.y + this.height
		);
	},
	
	// Same as contains(), except it takes a Point object as a parameter.
	containsPoint: function(p) {
		return p instanceof Point && this.contains(p.x, p.y);
	},
	
	// Determines whether the specified Rectangle object falls entirely within the region.
	containsRect: function(r) {
		return r instanceof Rectangle && (
			r.x >= this.x &&
			r.y >= this.y &&
			r.x + r.width <= this.x + this.width &&
			r.y + r.height <= this.y + this.height
		);
	},
	
	// Determines whether all points (x, y, width, height) are equal.
	equals: function(r) {
		return r instanceof Rectangle && (
			this.x == r.x &&
			this.y == r.y &&
			this.width == r.width &&
			this.height == r.height
		);
	},
	
	// Increases the size of the Rectangle object by scaling from the center point.
	inflate: function(dx, dy) {
		if(!isNaN(dx) && !isNaN(dy)) {
			this.x -= dx;
			this.y -= dy;
			this.width += dx * 2;
			this.height += dy *2;
		}
	},
	
	// Same as inflate(), except it takes a Point object as a parameter.
	inflatePoint: function(p) {
		if(p instanceof Point)
			this.inflate(p.x, p.y);
	},
	
	// Returns a new Rectangle object of the intersection points as its values.
	intersection: function(r) {
		if(r instanceof Rectangle) {
			var nr = new Rectangle();
			if(this.intersects(r)) {
				nr.x = this.x > r.x ? this.x : r.x;
				nr.y = this.y > r.y ? this.y : r.y;
				nr.width = (this.x + this.width < r.x + r.width ?
							this.x + this.width :
							r.x + r.width) - nr.x;
				nr.height = (this.y + this.height < r.y + r.height ?
							this.y + this.height :
							r.y + r.height) - nr.y;
			}
			return nr;
		}
	},
	
	// Determines whether the object specified intersects with this Rectangle object.
	intersects: function(r) {
		return r instanceof Rectangle && (
			r.width > 0 &&
			r.height > 0 &&
			this.x + this.width >= r.x &&
			this.x <= r.x + r.width &&
			this.y + this.height >= r.y &&
			this.y <= r.y + r.height
		);
	},
	
	// Determines whether or not this Rectangle object is empty.
	isEmpty: function() {
		return r.width <= 0 || r.height <= 0;
	},
	
	// Offsets the Rectangle object by the specified amount.
	offset: function(dx, dy) {
		if(!isNaN(dx)) this.x += dx;
		if(!isNaN(dy)) this.y += dy;
	},
	
	// Same as offset(), except it takes a Point object as a parameter.
	offsetPoint: function(p) {
		if(p instanceof Point)
			this.offset(p.x, p.y);
	},
	
	// Sets all of the Rectangle object's properties to 0.
	setEmpty: function() {
		this.x = 0;
		this.y = 0;
		this.width = 0;
		this.height = 0;
	},
	
	// Returns a string that contains the values of the x and y coordinates.
	toString: function() {
		return '(x=' + this.x + ', y=' + this.y + ', w=' + this.width + ', h=' + this.height + ')';
	},
	
	// Returns a new Rectangle object with the bounding box coordinates of the two Rectangle objects.
	union: function(r) {
		if(r instanceof Rectangle) {
			var nr = new Rectangle();
			nr.x = this.x < r.x ? this.x : r.x;
			nr.y = this.y < r.y ? this.y : r.y;
			nr.width = (this.x + this.width > r.x + r.width ?
						this.x + this.width :
						r.x + r.width) - nr.x;
			nr.height = (this.y + this.height > r.y + r.height ?
						this.y + this.height :
						r.y + r.height) - nr.y;
			return nr;
		}
	}
	
});
